var mongoose = require('mongoose'),
    PublicEnum = require('./Enum'),
    PublicFunction = require('./Function'),
    Transaction = require('./Transaction'),
    Schema = mongoose.Schema;

var entityClass = function(entityName, name, parentEntity){
    this.EntityName = entityName;
    this.Entity = mongoose.model(this.EntityName);
    this.Name = name;
    this.Parent = null;
    this.Childs = new Array();

    if(parentEntity != undefined && parentEntity != null){
        parentEntity.Childs.push(this);
        this.Parent = parentEntity;
    }

    this.save = function(records, resultFun) {
        if(records.length > 1){
            Transaction.BatchSaveByTran([{EntityName: this.EntityName, Records: records}], resultFun);
        }
        else {
            if (records[0].RowStatus == PublicEnum.RowStatus.Insert) {
                delete records[0]._id;
                delete records[0].RowStatus;
                this.insert(records[0], resultFun);
            }
            else if (records[0].RowStatus == PublicEnum.RowStatus.Modify) {
                delete records[0].RowStatus;
                this.update(records[0], resultFun);
            }
            else if (records[0].RowStatus == PublicEnum.RowStatus.Delete) {
                this.deleteById(records[0]._id, resultFun);
            }
        }
    };
    this.insert = function(record, resultFun){
        record.CreatedOn = new Date();
        record.SysVersion = 0;
        var self = this;

        var newEntity = new this.Entity(record);
        newEntity.save(function(err, newRecord){
            if(err){
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '【' + self.Name + '】' + '新增错误';
                newErr.message = err.message;
                if(resultFun != null && resultFun != undefined) {
                    resultFun(newErr);
                }
            }
            else{
                if(resultFun != null && resultFun != undefined) {
                    resultFun(null, newRecord);
                }
            }
        });
    };
    this.delete = function(condition, resultFun){
        var self = this;
        this.Entity.remove(condition).exec(function(err, result){
            if(err){
                var newErr = new Error();
                newErr.leval = 5;
                newErr.title = '【' + self.Name + '】' + '删除错误';
                newErr.message = err.message;
                if(resultFun != null && resultFun != undefined) {
                    resultFun(newErr);
                }
            }
            else{
                if(resultFun != null && resultFun != undefined) {
                    resultFun(null, result);
                }
            }
        });
    };
    this.deleteById = function(id, resultFun){
        if(this.Childs.length > 0){
            for(var i=0; i<this.Childs.length; i++){
                this.Childs[i].delete(eval("({" + this.EntityName + ": '" + id + "'})"));
            }
        }
        this.delete({_id: id}, function(err, result){
            if(err){
                if(resultFun != null && resultFun != undefined) {
                    resultFun(err);
                }
            }
            else{
                if(resultFun != null && resultFun != undefined) {
                    resultFun(null, result);
                }
            }
        });
    };
    this.deleteByIds = function(ids, resultFun){
        if(this.Childs.length > 0){
            for(var i=0; i<this.Childs.length; i++){
                this.Childs[i].delete(eval("({" + this.EntityName + ": {$in: ids}})"));
            }
        }
        this.delete({_id: {$in: ids}}, function(err, result){
            if(err){
                if(resultFun != null && resultFun != undefined) {
                    resultFun(err);
                }
            }
            else{
                if(resultFun != null && resultFun != undefined) {
                    resultFun(null, result);
                }
            }
        });
    };
    this.update = function(record, resultFun){
        var self = this;
        this.findById(record._id, '', function(err, result){
            if(err){
                err.leavl = 9;
                err.title = '【' + self.Name + '】' + '查询错误';
                if(resultFun != null && resultFun != undefined) {
                    resultFun(err);
                }
            }
            else{
                if(result == null){
                    var newErr = new Error();
                    newErr.leval = 9;
                    newErr.title = '【' + self.Name + '】' + '修改错误';
                    newErr.message = '修改数据不存在，可能被删除，请检查';
                    if(resultFun != null && resultFun != undefined) {
                        resultFun(newErr);
                    }
                }
                else if(record.SysVersion != null && record.SysVersion != undefined && result.SysVersion != record.SysVersion){
                    var newErr = new Error();
                    newErr.leval = 9;
                    newErr.title = '【' + self.Name + '】' + '并发异常';
                    newErr.message = '当前数据已被他人修改';
                    if(resultFun != null && resultFun != undefined) {
                        resultFun(newErr);
                    }
                }
                else {
                    record.SysVersion = result.SysVersion + 1;
                    record.ModifyOn = new Date();
                    self.Entity.update({_id: record._id}, {$set: record})
                        .exec(function(err, count) {
                            if (err) {
                                err.leavl = 9;
                                err.title = '【' + self.Name + '】' + '修改错误';
                                if(resultFun != null && resultFun != undefined) {
                                    resultFun(err);
                                }
                            } else {
                                self.Entity.findById(record._id, function(err, entity) {
                                    if (err) {
                                        err.leavl = 9;
                                        err.title = '【' + self.Name + '】' + '查询错误';
                                        err.message = '保存完成后，查找数据出错，' + err.message;
                                        if(resultFun != null && resultFun != undefined) {
                                            resultFun(errr);
                                        }
                                    } else {
                                        if(resultFun != null && resultFun != undefined) {
                                            resultFun(null, entity);
                                        }
                                    }
                                });
                            }
                        }
                    );
                }
            }
        });
    };
    this.updateByValue = function(condition, value, resultFun){
        var self = this;
        this.Entity.update(PublicFunction.formatCondition(condition), value).exec(function(err, result){
            if(err){
                var newErr = new Error();
                newErr.leval = 5;
                newErr.title = '【' + self.Name + '】' + '修改错误';
                newErr.message = err.message;
                if(resultFun != null && resultFun != undefined) {
                    resultFun(newErr);
                }
            }
            else{
                if(resultFun != null && resultFun != undefined) {
                    resultFun(null, result);
                }
            }
        });
    };

    this.find = function(condition, orderBy, populate, resultFun){
        if(populate == undefined || populate == null){
            populate = '';
        }
        this.Entity.find(PublicFunction.formatCondition(condition)).populate(populate).sort(orderBy).exec(resultFun);
    };
    this.findById = function(id, populate, resultFun){
        if(populate == undefined || populate == null){
            populate = '';
        }
        this.Entity.findById(id).populate(populate).exec(resultFun);
        //Entity.find({'_id' : mongoose.Types.ObjectId(id)}).exec(resultFun);
    };
    this.findOne = function(condition, populate, resultFun){
        if(populate == undefined || populate == null){
            populate = '';
        }
        this.Entity.findOne(PublicFunction.formatCondition(condition)).populate(populate).exec(resultFun);
    };
    this.search = function(text, filter, limit, resultFun){
        this.Entity.db.db.command({text: this.EntityName, search: text, filter: filter, limit: limit }, function(err, result){
            if(!err){
                var records = [];
                for(var i=0; i<result.results.length; i++) {
                    records.push(result.results[i].obj);
                }
                resultFun(err, records);
            }
            else{
                resultFun(err, reslut);
            }
        }); //executeDbCommand
        //{text: this.EntityName , {search: text, filter: filter, limit: limit }}
        //db.collection.runCommand( "text", { search: <string>,
        //    filter: <document>,
        //    project: <document>,
        //    limit: <number>,
        //    language: <string> } )
    };

    //聚合函数
    this.mapReduce = function(option,completeFun){
        this.Entity.mapReduce(option,completeFun);
    };
    this.aggregate = function(args, completeFun){
        this.Entity.aggregate(args).exec(function(err, data){
            completeFun(err, data);
        });
    };
    this.aggregateSum = function(groupFieldName, valueFieldName, condition, completeFun){
        this.aggregate([
            {$match: PublicFunction.formatCondition(condition)},
            {$group : {_id : '$' + groupFieldName, value : {$sum: '$' + valueFieldName}}},
            {$sort: {value: 1}}
        ], completeFun);
    };
    this.aggregateCount = function(groupFieldName, condition, completeFun){
        this.aggregate([
            {$match: PublicFunction.formatCondition(condition)},
            {$group : {_id : '$' + groupFieldName, value : {$sum: 1}}},
            {$sort: {value: 1}}
        ], completeFun);
    };
    this.aggregateAvg = function(groupFieldName, valueFieldName, condition, completeFun){
        this.aggregate([
            {$match: PublicFunction.formatCondition(condition)},
            {$group : {_id : '$' + groupFieldName, value : {$avg: '$' + valueFieldName}}},
            {$sort: {value: 1}}
        ], completeFun);
    };
    this.aggregateMax = function(groupFieldName, valueFieldName, condition, completeFun){
        this.aggregate([
            {$match: PublicFunction.formatCondition(condition)},
            {$group : {_id : '$' + groupFieldName, value : {$max: '$' + valueFieldName}}},
            {$sort: {value: 1}}
        ], completeFun);
    };
    this.aggregateMin = function(groupFieldName, valueFieldName, condition, completeFun){
        this.aggregate([
            {$match: PublicFunction.formatCondition(condition)},
            {$group : {_id : '$' + groupFieldName, value : {$min: '$' + valueFieldName}}},
            {$sort: {value: 1}}
        ], completeFun);
    };

    this.pageQuery = function(condition, orderBy, populate, pageNum, pageSize, resultFun) {
        if(populate == undefined || populate == null){
            populate = '';
        }
        this.Entity.find(PublicFunction.formatCondition(condition))
            .populate(populate).sort(orderBy)
            .skip(pageNum * pageSize)
            .limit(pageSize)
            .exec(resultFun);
    };
    this.queryRecordCount = function(condition, resultFun){
        this.Entity.find(PublicFunction.formatCondition(condition)).count().exec(resultFun);
    };
    this.findRecordIndex = function(id, condition, orderBy, resultFun){
        this.Entity.find(PublicFunction.formatCondition(condition), {'_id' : 1}).sort(orderBy)
            .exec(function(err, ids){
                if(err){
                    resultFun(err);
                }
                else{
                    resultFun(null, ids.toString().replace(/ /g,'').split(',').indexOf('{_id:' + id + '}'))
                }
            }
        );
    };
};

module.exports = entityClass;
